#include "EyerWASMEventLoop.hpp"

#include <stdio.h>
#include <emscripten.h>
#include <thread>

namespace Eyer
{
    EyerWASMEventLoop * EyerWASMEventLoop::instance = nullptr;
    std::mutex EyerWASMEventLoop::instanceMut;

    EyerWASMEventLoop * EyerWASMEventLoop::mainThreadInstance = nullptr;
    std::mutex EyerWASMEventLoop::mainThreadInstanceMut;

    EyerWASMEventLoop * EyerWASMEventLoop::GetInstance()
    {
        if(instance == nullptr) {
            std::unique_lock<std::mutex> lck(instanceMut);
            if(instance == nullptr) {
                instance = new EyerWASMEventLoop(true);
            }
        }
        return instance;
    }

    EyerWASMEventLoop * EyerWASMEventLoop::GetMainThreadInstance()
    {
        if(mainThreadInstance == nullptr) {
            std::unique_lock<std::mutex> lck(mainThreadInstanceMut);
            if(mainThreadInstance == nullptr) {
                mainThreadInstance = new EyerWASMEventLoop(false);
            }
        }
        return mainThreadInstance;
    }

    EyerWASMEventLoop::EyerWASMEventLoop(bool isNewThread)
    {
        if(isNewThread){
            t = new std::thread(&EyerWASMEventLoop::Run, this);
            t->detach();
        }
    }

    static void msg_loop(void * arg)
    {
        EyerWASMEventLoop * eventloop = (EyerWASMEventLoop *)arg;
        eventloop->EventLoop();
    }
    int EyerWASMEventLoop::Run()
    {
        emscripten_set_main_loop_arg(msg_loop, this, 0, 1);
        return 0;
    }

    int EyerWASMEventLoop::EventLoop()
    {
        std::unique_lock<std::mutex> lck(eventQueueMut);
        if(eventQueue.size() > 0){
            std::shared_ptr<EyerWASMEvent> event = eventQueue.front();
            eventQueue.pop();
            event->Run();
        }
        return 0;
    }

    int EyerWASMEventLoop::PutEvent(const std::shared_ptr<EyerWASMEvent> & event)
    {
        std::unique_lock<std::mutex> lck(eventQueueMut);
        eventQueue.push(event);
        return 0;
    }
}